package com.wtzz.police.base.config;

import com.wtzz.police.base.service.UserService;
import com.wtzz.police.base.util.component.JwtTokenUtil;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.validation.Validation;
import javax.validation.Validator;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private UserService userService;
    private JwtTokenUtil jwtTokenUtil;

    public WebSecurityConfig(UserService userService, JwtTokenUtil jwtTokenUtil) {
        this.userService = userService;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @Bean
    protected UserDetailsService customUserService() {
        return userService;
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() {
        return new JwtAuthenticationTokenFilter(this.jwtTokenUtil, userService);
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserService());
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public Validator validatorBean() {
        return Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 允许对于网站静态资源的无授权访问
        web.ignoring()
           .mvcMatchers("/",
                   "/resource/**",
                   "/*.html",
                   "/static/**",
                   "/webjars/springfox-swagger-ui/**",
                   "/swagger-resources/**",
                   "/swagger-resources",
                   "/v2/api-docs**",
                   "/doc.html**",
                   "/webjars/**");
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors()
                    .and()
                    // 由于使用的是JWT，我们这里不需要csrf
                    .csrf()
                    .disable()
                    // 基于token，所以不需要session
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/auth/login",
                            "/resource/**",
                            "/*.html",
                            "/static/**",
                            "/webjars/springfox-swagger-ui/**",
                            "/swagger-resources/**",
                            "/swagger-resources",
                            "/v2/api-docs**",
                            "/doc.html**",
                            "/webjars/**")
                    .permitAll()
                    // 除上面外的所有请求全部需要鉴权认证
                    .anyRequest()
                    .authenticated()
                    // 添加JWT filter
                    .and()
                    .exceptionHandling() //设置错误处理
                    .and()
                    .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
                    // 禁用缓存
                    .headers()
                    .cacheControl();
    }
}
